package com.learn.english.aspect;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.*;

/**
 * @author TISNIW
 * @version 1.0
 * @date 2025/6/21 20:05
 * @desc
 */

@Aspect
@Slf4j
@Component
public class LogAspect {


    // 定义切点（controller包下的所有类的所有方法）
    @Pointcut("execution(* com.learn.english.controller..*.*(..))")
    public void requestLog() {
        // 方法体为空，只是作为切点标识
    }

    // 在切点方法执行前执行
    @Before("requestLog()")
    public void doBefore() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) return;

        HttpServletRequest request = attributes.getRequest();

        log.info("==================================");
        log.info("请求地址: {} {}", request.getRemoteAddr(), request.getRequestURL().toString());
        log.info("请求方法: {}", request.getMethod());
    }

    // 在切点方法执行后执行（无论是否异常）
    @After("requestLog()")
    public void doAfter() {
        log.info("请求结束");
    }

    // 返回结果后执行（正常返回）
    @AfterReturning(pointcut = "requestLog()", returning = "result")
    public void doAfterReturning(Object result) {
        log.info("响应内容: {}", result);
    }

    // 异常时执行
    @AfterThrowing(pointcut = "requestLog()", throwing = "exception")
    public void doAfterThrowing(Throwable exception) {
        log.error("请求异常", exception);
    }

    // 环绕通知（可选）：可以控制方法执行前后逻辑
    @Around("requestLog()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        try {
            Object result = joinPoint.proceed(); // 执行目标方法
            log.info("请求耗时: {} ms", System.currentTimeMillis() - startTime);
            return result;
        } catch (Throwable throwable) {
            log.error("方法执行异常: {}", throwable.getMessage());
            throw throwable;
        }
    }
}
